/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controller;

import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import command.CommandFactory;

import model.Container;
import model.ContentType;
import model.Player;
import model.PlaylistRecord;
import tools.SEOTask;
import view.PlayerCanvas;
import config.Debug;
import config.Settings;
import data.HttpRequest;

/**
 * 
 * @author Yang Wang <yang@digitalmenubox.com>
 */
public class ScheduleController implements Runnable {

	private Player model = null;
	private PlayerCanvas view = null;
	private static Object videoLock = new Object();
	private static long nextRecordTimestamp = System.currentTimeMillis();
	private static boolean skipRecord = false;

	public static boolean isSkipRecord() {
		return skipRecord;
	}

	public static void setSkipRecord(boolean skipRecord) {
		ScheduleController.skipRecord = skipRecord;
	}

	public static long getNextRecordTimestamp() {
		return nextRecordTimestamp;
	}

	public static void setNextRecordTimestamp(long nextRecordTimestamp) {
		ScheduleController.nextRecordTimestamp = nextRecordTimestamp;
	}

	public ScheduleController(Player m, PlayerCanvas v) {
		this.model = m;
		this.view = v;
	}

	public static void main(String[] args) {
		try {
			// wait for a few seconds before the player starts
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}

		try {
			// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
			// UIManager.setLookAndFeel(new
			// com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel());
		} catch (Exception e) {
		}
		Settings.load();
		if (Settings.isConfigFileExist()) {
			// Settings.loadSettings();
			
		}
		Initializer.initializePlayer();
		// form browser plugins

		// UIUtils.setPreferredLookAndFeel();
		// NativeSwing.initialize();
		// NativeInterface.open();
		SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				Player p = Player.getInstance();
				PlayerCanvas c = PlayerCanvas.getInstance();
				ScheduleController controller = new ScheduleController(p, c);
				Thread controllerThread = new Thread(controller);
				controllerThread.setName("Controller Thread");
				controllerThread.start();
				config.Debug.log("The player is started", Debug.SYSTEM_LEVEL);

			}
		});
		// NativeInterface.runEventPump();

	}

	@Override
	public void run() {
		// this.view.addMouseListener(new AdminFrameMouseListener(null));
		this.view.display();

		// start downloading contents when the player starts
		Thread downloadOnStartup = new Thread(new Runnable() {

			@Override
			public void run() {
				Initializer.downloadContents();
			}
		});

		downloadOnStartup.start();

		Thread updater = new Thread(new UpdateChecker());
		Thread monitor = new Thread(new PlayerMonitor());
		Thread seotask = new Thread(new SEOTask(null));
		Thread statusReporter = new Thread(new PlayerStatusReporter());
		try {
			while (true) {
				int count = 0;

				PlayerCheckerClient.notifySocketServer();
				if (!updater.isAlive()) {
					updater = new Thread(new UpdateChecker());
					updater.setName("Player Updater Thread");
					updater.start();
				}
				if (!monitor.isAlive()) {
					monitor = new Thread(new PlayerMonitor());
					monitor.setName("Player Monitor Thread");
					monitor.start();
				}
				if (!seotask.isAlive()) {
					// test, pass a file name
					seotask = new Thread(new SEOTask(null));
					seotask.setName("SEO Thread");
					seotask.start();
				}
				if (!statusReporter.isAlive()) {
					// test, pass a file name
					statusReporter = new Thread(new PlayerStatusReporter());
					statusReporter.setName("Status Reporter");
					statusReporter.start();
				}
				if (!this.model.play()) {
					Thread.sleep(1000);
					continue;
				}
				Command.hideCursor();
				PlaylistRecord r = this.model.getCurrentPlaylistRecord();
				if (r != null) {

					if (r.getContent().getType() == ContentType.VIDEO) {
						synchronized (getVideoLock()) {
							getVideoLock().wait();
							// System.out.println("Wait finished");
						}
					} else {
						if (r.getPauseTime() > 0) {
							// r.setPauseTime(1);
						}
					}

					HttpRequest.postRecordId(r.getId());
					// System.out.print(String.format("Memmory:%7dkb ",
					// Runtime.getRuntime().freeMemory() / 1024));
					Debug.msg(r.toString());

					int pause = r.getPauseTime() * 1000;

					if (ScheduleController.isSkipRecord()) {
						ScheduleController.setSkipRecord(false);
						continue;
					}

					ScheduleController.setNextRecordTimestamp(System.currentTimeMillis() + pause);
					Thread.sleep(pause);

					while (this.model.isPaused() == true) {
						Thread.sleep(1000);
					}

					if (r.isClear() || (this.model.getNextRecord() != null && this.model.getNextRecord().getContainerId() == r.getContainerId())) {
						boolean nullPlayer = false;
						try {
							Container c = new Container(r.getContainerId());
							Container c2 = new Container(this.model.getNextRecord().getContainerId());
							if (c.getDepth() == Player.getInstance().getMaximumContainerIndex() && c2.getDepth() < c.getDepth()) {
								nullPlayer = true;
							}
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							if(r.isClear() || nullPlayer) {
								Player.getInstance().setCurrentPlaylistRecord(null);
							}
						}
					}

					if (r.isDisplayEventAfter()) {
						model.setPlayingInventory(true);
						// Debug.msg("Display event");
						this.model.getInventoryManager().play();
						model.setPlayingInventory(false);
					}

					if (!updater.isAlive()) {
						// Debug.log("Player Updater is not running",
						// Debug.EXCEPTION_LEVEL);
						updater = new Thread(new UpdateChecker());
						updater.start();
					}

					// if the player did not receive any mouse event within one
					// minute
					// move the mouse to the right side so that it is not
					// visible
					if (this.view.noActivityInOneMinute()) {
						Command.moveMouseToRightSide();
						this.view.setLastActionTime(0);
					}
				} else {
					Debug.msg("Current Record is Null");
					// Debug.log("Current Record is Null", Debug.WARNING_LEVEL);
				}
				ScheduleController.setSkipRecord(false);
			}
		} catch (InterruptedException ex) {
			Debug.log("Schedule Controller: Interrupted Exception", Debug.EXCEPTION_LEVEL);
		} catch (RuntimeException ex) {
			ex.printStackTrace();
			Debug.log("Runtime Exception " + ex.getMessage(), Debug.ERROR_LEVEL);
			CommandFactory.getInstance().restartPlayer();
		}
	}

	public static Object getVideoLock() {
		return videoLock;
	}
}
